#include <SDL.h>
#include <SDL_Image.h>
#include <assert.h>
#include <string>
#include "Memory.h"
#include "AllocationManager.h"
#include "MyGL.h"
#include "Texture.h"
#include "Error.h"

namespace Engine
{
	bool Texture::Load(const std::string& fileName)
	{
		SDL_Surface* surf = IMG_Load(fileName.c_str());

		if(!surf)
		{
			Error("Unable to load texture: " + fileName);
			return false;
		}

		// Code for loading in texture image for surface
		glGenTextures(1, &m_textureID);
		glBindTexture(GL_TEXTURE_2D, m_textureID);

		unsigned char* data = (unsigned char*) surf -> pixels;

		m_width = surf->w;
		m_height = surf->h;

		m_bpp = surf->format->BytesPerPixel;

		m_format = (m_bpp == 4)? GL_RGBA : GL_RGB;

		#ifdef MEM_DEBUG
			int size = m_width * m_height * m_bpp;
			TheAllocationManager::Instance() ->AddAllocation(Allocation(&m_textureID, size,__FILE__, __LINE__));
		#endif //MEM_DEBUG

		glTexImage2D(GL_TEXTURE_2D, 0, m_format, m_width, m_height, 0, m_format, GL_UNSIGNED_BYTE, data);

		//setting up mip maps
		gluBuild2DMipmaps(GL_TEXTURE_2D, m_format, m_width, m_height, m_format, GL_UNSIGNED_BYTE, data);

		SDL_FreeSurface(surf);

		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);

		m_name = fileName;

		return true;
	}

	bool Texture::Load(rapidxml::xml_node <>* node)
	{
		if(!node ->first_node("Texture"))
		{
			Error("Unable to find Texture FilePath in xml file");
			return false;
		}

		return Load(node ->first_node("FileName") ->value());
	}

	void Texture::Bind()
	{
		if(m_textureID != -1)
		{
			glEnable(GL_TEXTURE_2D); // To enable texture mapping
			glBindTexture(GL_TEXTURE_2D, m_textureID);
		}
	}

	Texture::~Texture()
	{
		if(m_textureID == -1) return;

		glDeleteTextures(1, &m_textureID);

		#ifdef MEM_DEBUG
			TheAllocationManager::Instance() ->RemoveAllocation(&m_textureID);
		#endif //MEM_DEBUG
	}
}